package com.beyondsoft.dtc.mobile.automation.uiautomator.service;

import com.beyondsoft.dtc.mobile.automation.base.GlobalConstants;
import com.beyondsoft.dtc.mobile.automation.base.GlobalConstants.ElementType;
import com.beyondsoft.dtc.mobile.automation.uiautomator.model.Coordinate;
import com.beyondsoft.dtc.mobile.automation.uiautomator.model.UiDumpModel;
import com.beyondsoft.dtc.mobile.automation.util.ShellUtil;
import com.beyondsoft.dtc.mobile.automation.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 元素定位用服务.
 *
 * @author scottche
 * @version 1.0 2016.4.19 初版创立.
 */
@Deprecated
public class UiAutomatorHandlerServiceNew {
	/**
	 * 提取的UI画面的xml文件名称.
	 */
	private final static String UI_DUMP_FILE_NAME = "uidump.xml";
	/**
	 * 存储在手机的位置.
	 */
	private final static String UI_XML_FILE_PATH = "/data/local/tmp/"
			+ UI_DUMP_FILE_NAME;
	private final Logger logger = LoggerFactory
			.getLogger(UiAutomatorHandlerServiceNew.class);
	/**
	 * ADB 命令路径
	 */
	private String adbPath;

	/**
	 * 连接目标机器标识.
	 */
	private String connectAddress;

	/**
	 * 匹配坐标值用正则
	 */
	private Pattern pattern = Pattern.compile("([0-9]+)");

	/*
	 * 获取系统临时文件存储目录，用以存储从移动设备pull下来的xml文件.
	 */
	private String tempDir = System.getProperty("java.io.tmpdir");

	/**
	 * /tmp/dumpfile
	 */
	private String temp = new File(tempDir + File.separator + "dumpfile")
			.getAbsolutePath();

	/**
	 * 存储解析xml文件后得到的所有node节点信息
	 */
	private List<UiDumpModel> dumps = null;

	/**
	 * 构造函数。创建存储手机发送的UI xml的文件夹.
	 *
	 * @param adbPath
	 *            adb命令路径
	 * @param connectAddress
	 *            目标移动设备
	 */
	public UiAutomatorHandlerServiceNew(String adbPath, String connectAddress) {
		this.adbPath = adbPath;
		this.connectAddress = connectAddress;
		this.temp += File.separator + connectAddress;

		File dumpFolder = new File(temp);
		if (!dumpFolder.exists()) {
			dumpFolder.mkdirs();
		}
	}

	/**
	 * 提取元素属性前需要刷新时调用.
	 */
	public void refresh() {
		// 目标机器截取当前画面UI XML信息
		String[] command = { adbPath, "-s", connectAddress, "shell",
				"uiautomator", "dump", UI_XML_FILE_PATH };
		ShellUtil.CommandResult commandResult = ShellUtil.execCommand(command);

		if (commandResult.isCommandSucceeded()) {
			// 将目标机器截取的UI信息拉到本地，以便进行解析.
			command = new String[] { adbPath, "-s", connectAddress, "pull",
					UI_XML_FILE_PATH, temp };
			commandResult = ShellUtil.execCommand(command);

			if (commandResult.isCommandSucceeded()) {
				command = new String[] { adbPath, "-s", connectAddress,
						"shell", "rm", UI_XML_FILE_PATH };
				ShellUtil.execCommand(command);
			}
		}

		File file = new File(temp + File.separator + UI_DUMP_FILE_NAME)
				.getAbsoluteFile();
		try {
			InputStream xml = new FileInputStream(file);
			dumps = new UiDumpXmlFileParser().getDumps(xml);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			dumps = new ArrayList<UiDumpModel>();
		}
	}

	/**
	 * 通过text定位单个元素
	 *
	 * @return 返回元素位置坐标
	 */
	public UiDumpModel findElementByKeyword(String keyword, String packageName) {
		UiDumpModel uiDumpModel = this.findElement(ElementType.TEXT.getValue(),
				keyword, packageName);
		return uiDumpModel == null ? this.findElement(
				ElementType.RESOURCE_ID.getValue(), keyword, packageName)
				: uiDumpModel;
	}

	/**
	 * 通过password定位单个元素
	 *
	 * @return 返回元素位置坐标
	 */
	public UiDumpModel findElementByPassword() {
		for (UiDumpModel dumpNode : dumps) {
			try {
				if (StringUtil.equalsIgnoreCase("true", dumpNode.getPassword())
						&& StringUtil.equalsIgnoreCase("true",
								dumpNode.getClickable())) {
					setCoordinate(dumpNode);
					return dumpNode;
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		return null;
	}

	/**
	 * 通过class定位单个元素
	 *
	 * @param className
	 *            className for searched target
	 * @return 返回元素位置坐标
	 */
	public UiDumpModel findElementByClass(String className) {
		for (UiDumpModel dumpNode : dumps) {
			try {
				if (dumpNode.getClassName() != null
						&& dumpNode.getClassName().contains(className)) {
					setCoordinate(dumpNode);
					return dumpNode;
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		return null;
	}

	public UiDumpModel findLastButton() {
		UiDumpModel lastNode = null;
		for (UiDumpModel dumpNode : dumps) {
			try {
				if (StringUtil
						.equalsIgnoreCase("true", dumpNode.getClickable())
						&& dumpNode.getClassName() != null
						&& dumpNode.getClassName().contains(
								GlobalConstants.CLASS_TYPE_BUTTON)) {
					setCoordinate(dumpNode);
					lastNode = dumpNode;
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		}
		return lastNode;
	}

	/**
	 * 获得前一个控件
	 * 
	 * @param currentNode
	 * @return UiDumpModel 如果没有返回null
	 */
	public UiDumpModel getPreNode(UiDumpModel currentNode) {
		int index = currentNode.getIndex();
		if (index <= 0) {
			return null;
		}

		UiDumpModel preNode = dumps.get(currentNode.getIndex() - 1);
		if (preNode != null) {
			setCoordinate(preNode);
		}
		return preNode;
	}

	/**
	 * 获得后一个控件
	 * 
	 * @param currentNode
	 * @return UiDumpModel 如果没有返回null
	 */
	public UiDumpModel getNextNode(UiDumpModel currentNode) {
		int index = currentNode.getIndex();
		if (index >= dumps.size() - 1) {
			return null;
		}

		UiDumpModel nextNode = dumps.get(currentNode.getIndex() + 1);
		if (nextNode != null) {
			setCoordinate(nextNode);
		}
		return nextNode;
	}

	/**
	 * 提取指定元素的中心点坐标.
	 *
	 * @param attributeId
	 *            Enum of element related text
	 * @param keyword
	 *            keyword for searched target text
	 * @return 指定元素的坐标
	 */
	private UiDumpModel findElement(int attributeId, String keyword,
			String packageName) {
		// 获取元素区域中心位置坐标.例如：[496,192][640,260]
		for (UiDumpModel dumpNode : dumps) {
			Boolean flag = false;
			try {
				String text = dumpNode.getText();
				switch (attributeId) {
				case 0:
					text = dumpNode.getText();
					break;
				case 1:
					text = dumpNode.getResourceId();
					break;
				case 2:
					text = dumpNode.getClassName();
					break;
				case 3:
					text = dumpNode.getChecked();
					break;
				case 4:
					text = dumpNode.getCheckable();
					break;
				case 5:
					text = dumpNode.getContentDesc();
					break;
				case 6:
					text = dumpNode.getClickable();
					break;
				case 8:
					text = dumpNode.getPassword();
					break;
				default:
					break;
				}

				flag = text.toLowerCase().equals(keyword.toLowerCase())
						&& "true".equalsIgnoreCase(dumpNode.getClickable());
				if (flag && !StringUtil.isEmpty(packageName)) {
					flag = dumpNode.getPackageName().toLowerCase()
							.startsWith(packageName.toLowerCase());
				}

				// for debug
				if (text.toLowerCase().contains(keyword.toLowerCase())) {
					logger.debug(
							">> getAttribute >>, text [{}], element src [{}], flag [{}], clickable [{}], pkgName [{}], element pkgName [{}]",
							keyword, text, flag, dumpNode.getClickable(),
							packageName, dumpNode.getPackageName());
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			// 匹配到指定的node后，提取该node所有属性.
			if (flag) {
				setCoordinate(dumpNode);
				return dumpNode;
			}
		}
		return null;
	}

	/**
	 * 设置中心的值
	 * 
	 * @param model
	 */
	private void setCoordinate(UiDumpModel model) {
		CharSequence input = model.getBounds();

		// 中心点坐标：bounds="[496,192][640,260].解析提取到数组里.
		Matcher mat = pattern.matcher(input);
		ArrayList<Integer> coords = new ArrayList<Integer>();
		while (mat.find()) {
			coords.add(new Integer(mat.group()));
		}

		// 提取元素的左上和右下坐标.
		int startX = coords.get(0);
		int startY = coords.get(1);
		int endX = coords.get(2);
		int endY = coords.get(3);

		// 指定元素的中心点坐标
		int centerCoordsX = (endX - startX) / 2 + startX;
		int centerCoordsY = (endY - startY) / 2 + startY;

		Coordinate coordinate = new Coordinate();

		coordinate.setX(centerCoordsX);
		coordinate.setY(centerCoordsY);

		model.setCoordinate(coordinate);
	}
}
